"""
# 指数变换：对数变换的推广
"""
# 对Yelp商家点评数量的Box-Cox变换
from scipy.stats import boxcox, probplot, norm
import pandas as pd
import json
import matplotlib.pyplot as plt

biz_file = open('../数据集/yelp_academic_dataset_business.json')
biz_df = pd.DataFrame([json.loads(x) for x in biz_file.readlines()])
# Box-Cox变换假定输入数据都是正的，检验数据的最小值以确定满足假定
print("满足Box-Cox变换使用前提假设" if biz_df['review_count'].min() >= 0 else "不满足Box-Cox变换使用前提假设")

# 设置输入参数lambda为0，使用对数变换（没有固定长度的位移）
biz_df['rc_log'] = boxcox(biz_df['review_count'], lmbda=0)
# 默认情况下，会找出使得输出最接近正态分布的lambda参数
biz_df['rc_bc'], bc_params = boxcox(biz_df['review_count'])

# 初始、对数变换后和Box-Cox变换后的点评数量直方图可视化
fig, (ax_orig, ax_log, ax_boxcox) = plt.subplots(3, 1)
# 初始
biz_df['review_count'].hist(ax=ax_orig, bins=100)
ax_orig.set_yscale('log')
ax_orig.tick_params(labelsize=14)
ax_orig.set_title('Review Counts Histogram', fontsize=14)
ax_orig.set_xlabel('')
ax_orig.set_ylabel('Occurrence', fontsize=14)

# 对数变换
biz_df['rc_log'].hist(ax=ax_log, bins=100)
ax_log.set_yscale('log')
ax_log.tick_params(labelsize=14)
ax_log.set_title('Log Transformed Counts Histogram', fontsize=14)
ax_log.set_xlabel('')
ax_log.set_ylabel('Occurrence', fontsize=14)

# Box-Cox变换
biz_df['rc_bc'].hist(ax=ax_boxcox, bins=100)
ax_boxcox.set_yscale('log')
ax_boxcox.tick_params(labelsize=14)
ax_boxcox.set_title('Box-Cox Transformed Counts Histogram (lambda={:.2f})'.format(bc_params), fontsize=14)
ax_boxcox.set_xlabel('')
ax_boxcox.set_ylabel('Occurrence', fontsize=14)

plt.savefig('./可视化/初始、对数变换后和Box-Cox变换后的点评数量直方图可视化.png')
plt.show()

# 初始、对数变换后和Box-Cox变换后的概率图，并和正态分布进行对比
fig, (ax_orig, ax_log, ax_boxcox) = plt.subplots(3, 1)
prob_orig = probplot(biz_df['review_count'], dist=norm, plot=ax_orig)
ax_orig.set_xlabel('')
ax_orig.set_title('Probplot against normal distribution')
prob_log = probplot(biz_df['rc_log'], dist=norm, plot=ax_log)
ax_log.set_xlabel('')
ax_log.set_title('Probplot after log transform')
prob_boxcox = probplot(biz_df['rc_bc'], dist=norm, plot=ax_boxcox)
ax_boxcox.set_xlabel('Theoretical quantiles')
ax_boxcox.set_title('Probplot after Box-Cox transform')

plt.savefig('./可视化/初始、对数变换后和Box-Cox变换后的概率图.png')
plt.show()
